#! /usr/bin/python2.4

# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
import unittest
import shutil
import sys

import gvn.hooks.info
import gvn.hooks.pre_commit.check_no_bad_chars
import svn.core
import svn.fs

# this is to move to its own class soon, and get functionality to create
# files and trees with arbitrary data as we get a better idea of what each
# hook needs
def make_test_txn(test_repo_name, filename):
  try:
    shutil.rmtree(test_repo_name)
  except:
    pass

  pool = svn.core.Pool()
  repos = svn.repos.create(test_repo_name, None, None, None, None, pool)
  fs = svn.repos.fs(repos)

  # Create transaction
  txn = svn.fs.begin_txn(fs,
                         0,               # head revision
                         pool)

  # Set basic revprops.
  svn.fs.change_txn_prop(txn, 'svn:author', 'basil', pool)
  svn.fs.change_txn_prop(txn, 'svn:log', 'log message', pool)

  txnroot = svn.fs.txn_root(txn, pool)

  # Create trunk directory.
  svn.fs.make_dir(txnroot, 'trunk', pool)

  # Create a file with 'some text\n'.
  svn.fs.make_file(txnroot, 'trunk/' + filename, pool)
  fp = svn.fs.apply_text(txnroot, 'trunk/' + filename, None, pool)
  svn.core.svn_stream_write(fp, 'some text\n')
  svn.core.svn_stream_close(fp)

  # We've built our transaction, now run tests.
  svn.fs.close_root(txnroot)

  return (repos, fs, txn, pool)


def delete_test_txn(txn, pool):
  """Delete/clean up transaction
  """
  svn.fs.abort_txn(txn, pool)


class BadCharsTests(unittest.TestCase):
  def _CheckFileName(self, filename):
    # We'll create a partial repository with a made up transaction
    # that we can run our hook against
    test_repo_name = "temprepo"

    # the transaction directory is overwritten in the object lower down
    argv = ['pre-commit', test_repo_name, 'txnname_bogus_ignored']
    hi = gvn.hooks.info.HookInfo(argv)

    (hi._repo, hi._fs, hi._txn, pool) = make_test_txn(test_repo_name, filename)
    try:
      # XXX better way to fake out logger?
      class logger:
        def warning(*args, **kwargs):
          pass
      return gvn.hooks.pre_commit.check_no_bad_chars.RunHook(hi, logger())
    finally:
      delete_test_txn(hi.txn, pool)
      shutil.rmtree(test_repo_name)

  def testNormalFile(self):
    """Check that normal files are ok
    """
    self.assertEquals(self._CheckFileName("normal_filename"), 0)

  def testNoSpace(self):
    """Check that space is disallowed
    """
    self.assertEquals(self._CheckFileName("space filename"), 255)

  # XXX(epg): Please fix this comment; what does it mean?  I know svn won't
  # allow tabs and newlines in filenames, but that doesn't tell me
  # what "test those in the trigger" means (also we have no triggers,
  # only hooks).

  # We can't test those because svn dies when you try to create such files
  # We test those in the hook just in case they made it through though
  #def testNoTab(self):
  #def testNoNewline(self):

  def testNoBadChars1(self):
    """Check that a random badchar ':' is disallowed
    """
    self.assertEquals(self._CheckFileName("bad:filename"), 255)

  def testNoBadChars2(self):
    """Check that a random badchar '*' is disallowed
    """
    self.assertEquals(self._CheckFileName("bad*filename"), 255)


if __name__ == '__main__':
  unittest.main()
